home *** CD-ROM | disk | FTP | other *** search
- /* This file is for functions having to do with key bindings,
- descriptions, help commands and startup file.
-
- written 11-feb-86 by Daniel Lawrence
- */
-
- #include <stdio.h>
- #include "estruct.h"
- #include "edef.h"
- #include "epath.h"
-
- extern int meta(), cex(), unarg(), ctrlg(); /* dummy prefix binding functions */
-
- help(f, n) /* give me some help!!!!
- bring up a fake buffer and read the help file
- into it with view mode */
- {
- register BUFFER *bp; /* buffer pointer to help */
- char *fname; /* ptr to file returned by flook() */
-
- /* first check if we are already here */
- bp = bfind("emacs.hlp", FALSE, BFINVS);
-
- if (bp == NULL) {
- fname = flook(pathname[1], FALSE);
- if (fname == NULL) {
- mlwrite("[Help file is not online]");
- return(FALSE);
- }
- }
-
- /* split the current window to make room for the help stuff */
- if (splitwind(FALSE, 1) == FALSE)
- return(FALSE);
- curwp = spltwp; curbp = curwp->w_bufp;
-
- if (bp == NULL) {
- /* and read the stuff in */
- if (getfile(fname, FALSE) == FALSE)
- return(FALSE);
- } else
- swbuffer(bp);
-
- /* make this window in VIEW mode, update all mode lines */
- curbp->b_mode |= MDVIEW;
- curbp->b_flag |= BFINVS;
- upmode();
- return(TRUE);
- }
-
- deskey(f, n) /* describe the command for a certain key */
-
- {
- register int c; /* key to describe */
- register char *ptr; /* string pointer to scan output strings */
- char outseq[NSTRING]; /* output buffer for command sequence */
- #if C86 | DECUSC
- int *getbind();
- #else
- int (*getbind())();
- #endif
-
- /* prompt the user to type us a key to describe */
- mlwrite(": describe-key ");
-
- /* get the command sequence to describe
- change it to something we can print as well */
- cmdstr(c = getckey(FALSE), &outseq[0]);
-
- /* and dump it out */
- ostring(outseq);
- ostring(" ");
-
- /* find the right ->function */
- if ((ptr = getfname(getbind(c))) == NULL)
- ptr = "Not Bound";
-
- /* output the command sequence */
- ostring(ptr);
- }
-
- /* bindtokey: add a new key to the key binding table */
-
- bindtokey(f, n)
-
- int f, n; /* command arguments [IGNORED] */
-
- {
- register unsigned int c;/* command key to bind */
- register (*kfunc)(); /* ptr to the requested function to bind to */
- register KEYTAB *ktp; /* pointer into the command table */
- register int found; /* matched command flag */
- char outseq[80]; /* output buffer for keystroke sequence */
- int (*getname())();
- #if C86 | DECUSC
- int (*fmeta)(), (*fcex)(), (*funarg)(), (*fctrlg)();
-
- fmeta = meta; fcex = cex; funarg = unarg; fctrlg = ctrlg;
- #else
- #define fmeta meta
- #define fcex cex
- #define funarg unarg
- #define fctrlg ctrlg
- #endif
-
-
- /* prompt the user to type in a key to bind */
- mlwrite(": bind-to-key ");
-
- /* get the function name to bind it to */
- kfunc = getname();
- if (kfunc == NULL) {
- mlwrite("[No such function]");
- return(FALSE);
- }
- ostring(" ");
-
- /* get the command sequence to bind */
- TTflush();
- c = getckey((kfunc == fmeta) || (kfunc == fcex) ||
- (kfunc == funarg) || (kfunc == fctrlg));
-
- /* change it to something we can print as well */
- cmdstr((int) c, &outseq[0]);
-
- /* and dump it out */
- ostring(outseq);
-
- /* if the function is a prefix key */
- if (kfunc == fmeta || kfunc == fcex ||
- kfunc == funarg || kfunc == fctrlg) {
- /* search for an existing binding for the prefix key */
- ktp = &keytab[0];
- #if DECEDT
- if (kfunc == funarg || kfunc == fctrlg)
- #endif
- while (ktp->k_fp != NULL) {
- if (ktp->k_fp == kfunc)
- chunbind(ktp->k_code);
- ++ktp;
- }
-
- /* reset the appropriate global prefix variable */
- if (kfunc == fmeta) metac = c;
- if (kfunc == fcex) ctlxc = c;
- if (kfunc == funarg) reptc = c;
- if (kfunc == fctrlg) abortc = c;
- }
-
- /* search the table to see if it exists */
- ktp = &keytab[0];
- found = FALSE;
- while (ktp->k_fp != NULL) {
- if (ktp->k_code == c) {
- found = TRUE;
- break;
- }
- ++ktp;
- }
-
- if (found) { /* it exists, just change it then */
- if (ktp->k_fp == fmeta) metac = 0;
- if (ktp->k_fp == fcex) ctlxc = 0;
- if (ktp->k_fp == funarg) reptc = 0;
- if (ktp->k_fp == fctrlg) abortc = 0;
-
- ktp->k_fp = kfunc;
- if (c > 0 && c < NFBIND) fkeytab[c] = kfunc;
- else if (c == (FUNC|'C')) ffuncc = kfunc;
- fkeylast.k_code = c;
- fkeylast.k_fp = kfunc;
- } else { /* otherwise we need to add it to the end */
- /* if we run out of binding room, bitch */
- if (ktp >= &keytab[NBINDS]) {
- mlwrite("Binding table FULL!");
- return(FALSE);
- }
-
- ktp->k_code = c; /* add keycode */
- ktp->k_fp = kfunc; /* and the function pointer */
- ++ktp; /* and make sure the next is null */
- ktp->k_code = 0;
- ktp->k_fp = NULL;
- if (c > 0 && c < NFBIND) fkeytab[c] = kfunc;
- else if (c == (FUNC|'C')) ffuncc = kfunc;
- fkeylast.k_code = c;
- fkeylast.k_fp = kfunc;
- }
- return(TRUE);
- }
-
- /* unbindkey: delete a key from the key binding table */
-
- unbindkey(f, n)
-
- int f, n; /* command arguments [IGNORED] */
-
- {
- register int c; /* command key to unbind */
- char outseq[80]; /* output buffer for keystroke sequence */
-
- /* prompt the user to type in a key to unbind */
- mlwrite(": unbind-key ");
-
- /* get the command sequence to unbind */
- c = getckey(FALSE); /* get a command sequence */
-
- /* change it to something we can print as well */
- cmdstr(c, &outseq[0]);
-
- /* and dump it out */
- ostring(outseq);
-
- /* if it isn't bound, bitch */
- if (chunbind(c) == FALSE) {
- mlwrite("[Key not bound]");
- return(FALSE);
- }
- return(TRUE);
- }
-
- chunbind(c)
-
- int c; /* command key to unbind */
-
- {
- register KEYTAB *ktp; /* pointer into the command table */
- register KEYTAB *sktp; /* saved pointer into the command table */
- register int found; /* matched command flag */
-
- /* search the table to see if the key exists */
- ktp = &keytab[0];
- found = FALSE;
- while (ktp->k_fp != NULL) {
- if (ktp->k_code == c) {
- found = TRUE;
- break;
- }
- ++ktp;
- }
-
- /* if it isn't bound, bitch */
- if (!found)
- return(FALSE);
-
- /* save the pointer and scan to the end of the table */
- sktp = ktp;
- while (ktp->k_fp != NULL)
- ++ktp;
- --ktp; /* backup to the last legit entry */
-
- /* copy the last entry to the current one */
- sktp->k_code = ktp->k_code;
- sktp->k_fp = ktp->k_fp;
-
- /* null out the last one */
- ktp->k_code = 0;
- ktp->k_fp = NULL;
-
- /* clear in fast lookup area */
- if (c > 0 && c < NFBIND) fkeytab[c] = NULL;
- else if (c == (FUNC|'C')) ffuncc = NULL;
- fkeylast.k_code = keytab[0].k_code;
- fkeylast.k_fp = keytab[0].k_fp;
-
- return(TRUE);
- }
-
- desbind(f, n) /* describe bindings
- bring up a fake buffer and list the key bindings
- into it with view mode */
-
- #if APROP
- {
- buildlist(TRUE, "");
- }
-
- apro(f, n) /* Apropos (List functions that match a substring) */
-
- {
- char mstring[NSTRING]; /* string to match cmd names to */
- int status; /* status return */
-
- status = mlreply("Apropos string: ", mstring, NSTRING - 1);
- if (status != TRUE)
- return(status);
-
- return(buildlist(FALSE, mstring));
- }
-
- buildlist(type, mstring) /* build a binding list (limited or full) */
-
- int type; /* true = full list, false = partial list */
- char *mstring; /* match string if a partial list */
-
- #endif
- {
- #if ST520 & LATTICE
- #define register
- #endif
- register WINDOW *wp; /* scanning pointer to windows */
- register KEYTAB *ktp; /* pointer into the command table */
- register NBIND *nptr; /* pointer into the name binding table */
- register BUFFER *bp; /* buffer to put binding list into */
- int cpos; /* current position to use in outseq */
- char outseq[80]; /* output buffer for keystroke sequence */
-
- /* split the current window to make room for the binding list */
- if (splitwind(FALSE, 1) == FALSE)
- return(FALSE);
- curwp = spltwp; curbp = curwp->w_bufp;
-
- /* and get a buffer for it */
- bp = bfind("Binding list", TRUE, 0);
- if (bp == NULL || bclear(bp) == FALSE) {
- mlwrite("Can not display binding list");
- return(FALSE);
- }
-
- /* let us know this is in progress */
- mlwrite("[Building binding list]");
-
- /* disconect the current buffer */
- if (--curbp->b_nwnd == 0) { /* Last use. */
- curbp->b_fcol = curwp->w_fcol;
- curbp->b_dotp = curwp->w_dotp;
- curbp->b_doto = curwp->w_doto;
- curbp->b_markp = curwp->w_markp;
- curbp->b_marko = curwp->w_marko;
- }
-
- /* connect the current window to this buffer */
- curbp = bp; /* make this buffer current in current window */
- bp->b_mode = 0; /* no modes active in binding list */
- bp->b_nwnd++; /* mark us as more in use */
- wp = curwp;
- wp->w_bufp = bp;
- wp->w_linep = bp->b_linep;
- wp->w_flag = WFHARD|WFFORCE;
- wp->w_dotp = bp->b_dotp;
- wp->w_doto = bp->b_doto;
- wp->w_markp = NULL;
- wp->w_marko = 0;
-
- /* build the contents of this window, inserting it line by line */
- nptr = &names[0];
- while (nptr->n_func != NULL) {
-
- /* add in the command name */
- strcpy(outseq, nptr->n_name);
- cpos = strlen(outseq);
-
- #if APROP
- /* if we are executing an apropos command..... */
- if (type == FALSE &&
- /* and current string doesn't include the search string */
- strinc(outseq, mstring) == FALSE)
- goto fail;
- #endif
- /* search down any keys bound to this */
- ktp = &keytab[0];
- while (ktp->k_fp != NULL) {
- if (ktp->k_fp == nptr->n_func) {
- /* pad out some spaces */
- while (cpos < 25)
- outseq[cpos++] = ' ';
-
- /* add in the command sequence */
- cmdstr(ktp->k_code, &outseq[cpos]);
-
- /* and add it as a line into the buffer */
- linstr(outseq);
- lnewline();
-
- cpos = 0; /* and clear the line */
- }
- ++ktp;
- }
-
- /* if no key was bound, we need to dump it anyway */
- if (cpos > 0) {
- outseq[cpos] = 0;
- linstr(outseq);
- lnewline();
- }
-
- fail: /* and on to the next name */
- ++nptr;
- }
-
- curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */
- curbp->b_flag &= ~BFCHG; /* don't flag this as a change */
- wp->w_dotp = lforw(bp->b_linep);/* back to the beginning */
- wp->w_doto = 0;
- upmode(); /* and update ALL mode lines */
- mlwrite("[Use ^X 0 to return to one window]");
- return(TRUE);
- }
-
- #if APROP
- strinc(source, sub) /* does source include sub? */
-
- char *source; /* string to search in */
- char *sub; /* substring to look for */
-
- {
- char *sp; /* ptr into source */
- char *nxtsp; /* next ptr into source */
- char *tp; /* ptr into substring */
-
- /* for each character in the source string */
- sp = source;
- while (*sp) {
- tp = sub;
- nxtsp = sp;
-
- /* is the substring here? */
- while (*tp) {
- if (*nxtsp++ != *tp)
- break;
- else
- tp++;
- }
-
- /* yes, return a success */
- if (*tp == 0)
- return(TRUE);
-
- /* no, onward */
- sp++;
- }
- return(FALSE);
- }
- #endif
-
- /* get a command key sequence from the keyboard */
-
- unsigned int getckey(mflag)
-
- int mflag; /* going for a meta sequence? */
-
- {
- register unsigned int c; /* character fetched */
- char tok[NSTRING]; /* command incoming */
-
- /* check to see if we are executing a command line */
- if (clexec) {
- macarg(tok); /* get the next token */
- return(stock(tok));
- }
-
- /* or the normal way */
- if (mflag)
- c = get1key();
- else
- c = getcmd();
- return(c);
- }
-
- /* execute the startup file */
-
- startup(sfname)
-
- char *sfname; /* name of startup file (null if default) */
-
- {
- char *fname; /* resulting file name to execute */
-
- /* look up the startup file */
- if (*sfname != 0)
- fname = flook(sfname, TRUE);
- else
- fname = flook(pathname[0], TRUE);
-
- /* if it isn't around, don't sweat it */
- if (fname == NULL)
- return(TRUE);
-
- /* otherwise, execute the sucker */
- return(dofile(fname));
- }
-
- /* Look up the existance of a file along the normal or PATH
- environment variable. Look first in the HOME directory if
- asked and possible
- */
-
- char *flook(fname, hflag)
-
- char *fname; /* base file name to search for */
- int hflag; /* Look in the HOME environment variable first? */
-
- {
- register char *home; /* path to home directory */
- register char *path; /* environmental PATH variable */
- register char *sp; /* pointer into path spec */
- register int i; /* index */
- static char fspec[NSTRING]; /* full path spec to search */
- char *getenv();
-
- #if ENVFUNC
-
- if (hflag) {
- home = getenv("HOME");
- if (home != NULL) {
- /* build home dir file spec */
- strcpy(fspec, home);
- #if VMS
- #else
- #if MSDOS
- strcat(fspec, "\\");
- #else
- strcat(fspec, "/");
- #endif
- #endif
- strcat(fspec, fname);
-
- /* and try it out */
- if (ffropen(fspec, FALSE) == FIOSUC) {
- ffclose();
- return(fspec);
- }
- }
- }
- #endif
-
- /* always try the current directory first */
- if (ffropen(fname, FALSE) == FIOSUC) {
- ffclose();
- return(fname);
- }
-
- #if ENVFUNC && (VMS == 0)
- /* get the PATH variable */
- path = getenv("PATH");
- if (path != NULL)
- while (*path) {
-
- /* build next possible file spec */
- sp = fspec;
- while (*path && (*path != PATHCHR))
- *sp++ = *path++;
- #if VMS
- #else
- #if MSDOS
- if (sp > fspec && *(sp-1) != '\\') *sp++ = '\\';
- #else
- if (sp > fspec && *(sp-1) != '/') *sp++ = '/';
- #endif
- #endif
- *sp = 0;
- strcat(fspec, fname);
-
- /* and try it out */
- if (ffropen(fspec, FALSE) == FIOSUC) {
- ffclose();
- return(fspec);
- }
-
- if (*path == PATHCHR)
- ++path;
- }
- #endif
-
- /* look it up via the old table method */
- for (i=2; i < NPNAMES; i++) {
- strcpy(fspec, pathname[i]);
- strcat(fspec, fname);
-
- /* and try it out */
- if (ffropen(fspec, FALSE) == FIOSUC) {
- ffclose();
- return(fspec);
- }
- }
-
- return(NULL); /* no such luck */
- }
-
- cmdstr(c, seq) /* change a key command to a string we can print out */
-
- int c; /* sequence to translate */
- char *seq; /* destination string for sequence */
-
- {
- char *ptr; /* pointer into current position in sequence */
-
- ptr = seq;
-
- /* apply meta sequence if needed */
- if (c & META) {
- *ptr++ = 'M';
- *ptr++ = '-';
- }
-
- /* apply ^X sequence if needed */
- if (c & CTLX) {
- *ptr++ = '^';
- *ptr++ = 'X';
- }
-
- /* apply SPEC sequence if needed */
- if (c & SPEC) {
- *ptr++ = 'F';
- *ptr++ = 'N';
- }
-
- /* apply control sequence if needed */
- if (c & CTRL) {
- *ptr++ = '^';
- }
-
- c = c & 255; /* strip the prefixes */
-
- /* and output the final sequence */
-
- *ptr++ = c;
- *ptr = 0; /* terminate the string */
- }
-
- /* This function looks a key binding up in the binding table */
-
- #if C86 | DECUSC
- int *getbind(c)
- #else
- int (*getbind(c))()
- #endif
-
- int c; /* key to find what is bound to it */
-
- {
- register KEYTAB *ktp;
-
- if (c > 0 && c < NFBIND) return(fkeytab[c]);
- else if (c == (FUNC|'C')) return(ffuncc);
- else if (c == fkeylast.k_code) return(fkeylast.k_fp);
-
- ktp = &keytab[0]; /* Look in key table. */
- while (ktp->k_fp != NULL) {
- if (ktp->k_code == c) {
- fkeylast.k_code = c;
- fkeylast.k_fp = ktp->k_fp;
- return(ktp->k_fp);
- }
- ++ktp;
- }
-
- /* no such binding */
- return(NULL);
- }
-
- /* getfname: This function takes a ptr to function and gets the name
- associated with it
- */
-
- char *getfname(func)
-
- int (*func)(); /* ptr to the requested function to bind to */
-
- {
- register NBIND *nptr; /* pointer into the name binding table */
-
- /* skim through the table, looking for a match */
- nptr = &names[0];
- while (nptr->n_func != NULL) {
- if (nptr->n_func == func)
- return(nptr->n_name);
- ++nptr;
- }
- return(NULL);
- }
-
- /* match fname to a function in the names table
- and return any match or NULL if none */
-
- #if C86 | DECUSC
- int *fncmatch(fname)
- #else
- int (*fncmatch(fname))()
- #endif
-
- char *fname; /* name to attempt to match */
-
- {
- register NBIND *ffp; /* pointer to entry in name binding table */
-
- /* scan through the table, returning any match */
- ffp = &names[0];
- while (ffp->n_func != NULL) {
- if (*fname == ffp->n_name[0] && strcmp(fname, ffp->n_name) == 0)
- return(ffp->n_func);
- ++ffp;
- }
- return(NULL);
- }
-
- /* stock: String key name TO Command Key */
-
- unsigned int stock(keyname)
-
- char *keyname; /* name of key to translate to Command key form */
-
- {
- register unsigned int c; /* key sequence to return */
- int i, code;
-
- /* parse it up */
- c = 0;
-
- /* first, the META prefix */
- if (*keyname == 'M' && *(keyname+1) == '-') {
- c = META;
- keyname += 2;
- }
-
- /* the control-x prefix */
- if (*keyname == '^' && *(keyname+1) == 'X') {
- c |= CTLX;
- keyname += 2;
- }
-
- /* next the function prefix */
- if (*keyname == 'F' && *(keyname+1) == 'N') {
- c |= SPEC;
- keyname += 2;
- }
-
- /* control-x as well... (but not with FN) */
- if (*keyname == '^' && *(keyname+1) == 'X' && !(c & (SPEC|CTLX))) {
- c |= CTLX;
- keyname += 2;
- }
-
- /* a control char? */
- if (*keyname == '^' && *(keyname+1) != 0) {
- c |= CTRL;
- ++keyname;
- }
-
- /* simplify entry of VT200 escape + [ + number + ~ sequences */
- if ((c & SPEC) && *keyname >= '0' && *keyname <= '9' && *(keyname+1)) {
- code = 0;
- for(i = 0; i < 4 && *keyname >= '0' && *keyname <= '9'; i++)
- code = code*10 + *keyname++ - '0';
- code &= 0xFF;
- if (code>=0x00 && code<=0x1F) code = CTRL | (code+'@');
- c |= code;
- }
- else {
- if (*keyname < 32) {
- c |= CTRL;
- *keyname += '@';
- }
-
- /* make sure we are not lower case (not with function keys)*/
- if (*keyname >= 'a' && *keyname <= 'z' && !(c & SPEC))
- *keyname -= 32;
-
- /* the final sequence... */
- c |= *keyname;
- }
-
- return(c);
- }
-
- char *transbind(skey) /* string key name to binding name.... */
-
- char *skey; /* name of keey to get binding for */
-
- {
- char *bindname;
- unsigned int stock();
- #if C86 | DECUSC
- int *getbind();
- #else
- int (*getbind())();
- #endif
-
- bindname = getfname(getbind( (int) stock(skey)));
- if (bindname == NULL)
- bindname = "ERROR";
-
- return(bindname);
- }
-
- fkeyinit() /* init fast binding lookup table */
- {
- register int c;
- register KEYTAB *ktp;
-
- for(c = 0; c < NFBIND; c++) fkeytab[c] = NULL;
- ffuncc = NULL;
-
- ktp = &keytab[0];
- while (ktp->k_fp != NULL) {
- if (ktp->k_code > 0 && ktp->k_code < NFBIND)
- fkeytab[ ktp->k_code ] = ktp->k_fp;
- else if (ktp->k_code == (FUNC|'C'))
- ffuncc = ktp->k_fp;
- ++ktp;
- }
-
- fkeylast.k_code = keytab[0].k_code;
- fkeylast.k_fp = keytab[0].k_fp;
- }
-
-